﻿using System.Text.RegularExpressions;

namespace Away.Stocks.Services.Implements;

public class StockService : IStockService
{
    private readonly IHttpClientFactory _httpClientFactory;
    public StockService(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task<Dictionary<string, Stock>> GetStockList(string stockcodes)
    {
        using var httpClient = _httpClientFactory.CreateClient();
        httpClient.DefaultRequestHeaders.Referrer = new Uri("https://finance.sina.com.cn/");

        var marketId = ToMarketId(stockcodes);
        var url = $"https://hq.sinajs.cn/list={marketId}";
        var response = await httpClient.GetAsync(url);
        if (!response.IsSuccessStatusCode)
        {
            return new Dictionary<string, Stock>();
        }
        var res = await response.Content.ReadAsStringAsync();
        var markets = ToEntities(res);
        return markets;
    }


    private static string ToMarketId(string stockcode)
    {
        if (stockcode.StartsWith('6') || stockcode.StartsWith('0'))
        {
            return $"sh{stockcode}";
        }
        if (stockcode.StartsWith('3'))
        {
            return $"sz{stockcode}";
        }
        return stockcode;
    }

    private static Dictionary<string, Stock> ToEntities(string res)
    {
        var dic = new Dictionary<string, Stock>();
        var strArr = res.Split("\n", StringSplitOptions.RemoveEmptyEntries);
        foreach (var str in strArr)
        {
            var pattern_code = @"var hq_str_(?<code>.*)=";
            var match_code = Regex.Match(str, pattern_code);
            var stockcode = match_code.Result("${code}");

            var pattern = @"(['""])(?<market>.*)(['""])";
            var match = Regex.Match(str, pattern);
            if (match == null || !match.Success)
            {
                continue;
            }
            var market = match.Result("${market}");
            if (string.IsNullOrWhiteSpace(market))
            {
                continue;
            }
            var items = market.Split(",", StringSplitOptions.RemoveEmptyEntries);
            if (items.Length != 33)
            {
                continue;
            }
            var entity = ToEntity(items);
            entity.StockCode = stockcode;
            dic.TryAdd(stockcode, entity);
        }
        return dic;
    }

    private static Stock ToEntity(string[] arr)
    {
        Stock entity = new();
        entity.StockName = arr[0];
        entity.TodayStartPrice = Convert.ToDecimal(arr[1]);
        entity.LastdayEndPrice = Convert.ToDecimal(arr[2]);
        entity.NowPrice = Convert.ToDecimal(arr[3]);
        entity.TodayMaxPrice = Convert.ToDecimal(arr[4]);
        entity.TodayMinPrice = Convert.ToDecimal(arr[5]);
        entity.BuyBiddingPrice = Convert.ToDecimal(arr[6]);
        entity.SellBiddingPrice = Convert.ToDecimal(arr[7]);
        entity.TradingNumber = Convert.ToInt32(arr[8]);
        entity.TradingVolume = Convert.ToDecimal(arr[9]);
        entity.DateTime = Convert.ToDateTime($"{arr[30]} {arr[31]}");

        entity.BuyLevel = new List<MarketPriceLevel>
        {
            new MarketPriceLevel(Convert.ToDecimal(arr[11]), Convert.ToInt32(arr[10])),
            new MarketPriceLevel(Convert.ToDecimal(arr[13]), Convert.ToInt32(arr[12])),
            new MarketPriceLevel(Convert.ToDecimal(arr[15]), Convert.ToInt32(arr[14])),
            new MarketPriceLevel(Convert.ToDecimal(arr[17]), Convert.ToInt32(arr[16])),
            new MarketPriceLevel(Convert.ToDecimal(arr[19]), Convert.ToInt32(arr[18])),
        };

        entity.SellLevel = new List<MarketPriceLevel>
        {
            new MarketPriceLevel(Convert.ToDecimal(arr[21]), Convert.ToInt32(arr[20])),
            new MarketPriceLevel(Convert.ToDecimal(arr[23]), Convert.ToInt32(arr[22])),
            new MarketPriceLevel(Convert.ToDecimal(arr[25]), Convert.ToInt32(arr[24])),
            new MarketPriceLevel(Convert.ToDecimal(arr[27]), Convert.ToInt32(arr[26])),
            new MarketPriceLevel(Convert.ToDecimal(arr[29]), Convert.ToInt32(arr[28])),
        };
        return entity;
    }

}
